/* Copyright (c) 2025 Beijing Semidrive Technology Corporation
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/** *****************************************************************************************************
 * \file     Mbox_Ip.c                                                                                  *
 * \brief    AUTOSAR 4.3.1 MCAL mailbox low level Driver                                                *
 *                                                                                                      *
 * <table>                                                                                              *
 * <tr><th>Date           <th>Version                                                                   *
 * <tr><td>2024/11/06     <td>1.0.0                                                                     *
 * </table>                                                                                             *
 *******************************************************************************************************/
/********************************************************************************************************
 *                                      Include header files                                            *
 *******************************************************************************************************/
#include "Mbox_Ip.h"

#if (defined(CFG_PLATFORM_MCAL))
#include "RegHelper.h"
#define MAILBOX_START_SEC_CODE
#include "Mailbox_MemMap.h"
#endif

/********************************************************************************************************
 *                                 Global Macro definition                                              *
 *******************************************************************************************************/
#if (defined(COINFIG_MBOX_POLL_PERIOD) && (COINFIG_MBOX_POLL_PERIOD > 0))
#define MBOX_IP_POLL_DELAY COINFIG_MBOX_POLL_PERIOD
#else
#define MBOX_IP_POLL_DELAY 10U
#endif

/********************************************************************************************************
 *                                  Private Function Declarations                                       *
 *******************************************************************************************************/
/** *****************************************************************************************************
 * \brief This function reads the mailbox register with 32bits.
 *
 * \verbatim
 * Syntax             : uint32_t Mbox_Ip_Readl(
 *                          uint32_t base, uint32_t offset)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - the base physical address
 *                      offset - the offset of the base address
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : the read value
 *
 * Description        : Read the mailbox register and return the 32bits value.
 * \endverbatim
 *******************************************************************************************************/
static inline uint32_t Mbox_Ip_Readl(uint32_t base, uint32_t offset)
{
    return readl(base + offset);
}

/** *****************************************************************************************************
 * \brief This function writes the mailbox register with 32bits.
 *
 * \verbatim
 * Syntax             : void Mbox_Ip_Writel(uint32_t base,
 *                          uint32_t offset, uint32_t val)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - the base physical address
 *                      offset - the offset of the base address
 *                      val - the value to be written
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Write the mailbox register with 32bits value.
 *******************************************************************************************************/
static inline void Mbox_Ip_Writel(uint32_t base, uint32_t offset, uint32_t val)
{
    writel(val, (base + offset));
}

/** *****************************************************************************************************
 * \brief This function sets the master id for mailbox.
 *
 * \verbatim
 * Syntax             : void Mbox_Ip_SetMasterId(uint32_t base)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - the base physical address
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Set the master id for mailbox.
 *******************************************************************************************************/
void Mbox_Ip_SetMasterId(uint32_t base)
{
    uint32_t idIndex;
    uint32_t midTemp;
    uint32_t midValue;

    for (idIndex = 0U; idIndex < MBOX_PROC_NUM; idIndex++)
    {
        /* PRQA S 4461 1 */
        midTemp = MBOX_PROC_TO_MASTER_ID(idIndex);
        /** #10 set and lock 4 id for each master with the same value */
        midValue = ((0x80U + midTemp) << 24U) | ((0x80U + midTemp) << 16U) |
                   ((0x80U + midTemp) << 8U) | (0x80U + midTemp);
        Mbox_Ip_Writel(base, MBOX_MASTERID(idIndex), midValue);
    }
}

/** *****************************************************************************************************
 * \brief This function gets the master id of mailbox.
 *
 * \verbatim
 * Syntax             : uint16_t Mbox_Ip_GetMasterId(uint16_t procId)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : procId - the target core id
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : The master id
 *
 * Description        : Get the master id.
 * \endverbatim
 *******************************************************************************************************/
uint16_t Mbox_Ip_GetMasterId(uint16_t procId)
{
    /* PRQA S 4461 1 */
    return (uint16_t)(MBOX_PROC_TO_MASTER_ID(procId));
}

/** *****************************************************************************************************
 * \brief This function gets the cpu user id of mailbox.
 *
 * \verbatim
 * Syntax             : uint16_t Mbox_Ip_GetCpuUserId(uint32_t base)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - the base physical address
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : The cpu user id of mailbox
 *
 * Description        : Get the cpu user id of mailbox.
 * \endverbatim
 *******************************************************************************************************/
uint16_t Mbox_Ip_GetCpuUserId(uint32_t base)
{
    /* PRQA S 4461 1 */
    return Mbox_Ip_Readl(base, MBOX_CPUUSERID) & 0x0FU;
}

/** *****************************************************************************************************
 * \brief This function checks if the master id is valid.
 *
 * \verbatim
 * Syntax             : int32_t Mbox_Ip_CheckMasterId(uint32_t base)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - the base physical address
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : The result of the check
 *
 * Description        : Check if the master id is valid.
 * \endverbatim
 *******************************************************************************************************/
int32_t Mbox_Ip_CheckMasterId(uint32_t base)
{
    uint32_t idIndex;
    uint32_t valIndex;
    uint32_t midValue;
    /* PRQA S 4423 1 */
    int32_t ret = MBOX_OK;

    for (idIndex = 0U; idIndex < MBOX_PROC_ID_NUM; idIndex++)
    {
        /** #10 check 4 id of each master if they are the no-zero value */
        midValue = Mbox_Ip_Readl(base, MBOX_MASTERID(idIndex));

        for (valIndex = 0U; valIndex <= 3U; valIndex ++)
        {
            if ((midValue & 0xFFU) == 0U)
            {
                /* PRQA S 4423 1 */
                ret = MBOX_ERR_INVALID_MASTERID;
                break;
            }
            midValue >>= 8U;
        }
    }

    return ret;
}

/* PRQA S 1505 EOF */
/** *****************************************************************************************************
 * \brief This function fills the mailbox message header.
 *
 * \verbatim
 * Syntax             : void Mbox_Ip_FillMsgHeader(uint32_t base,
 *                          uint8_t msgId, uint16_t mdp, uint16_t len)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - the base physical address
 *                    : msgId - the message id
 *                    : mdp - the target core mask
 *                    : len - the length of the message
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Fill the mailbox message header.
 * \endverbatim
 *******************************************************************************************************/
void Mbox_Ip_FillMsgHeader(uint32_t base, uint8_t msgId, uint16_t mdp, uint16_t len)
{
    uint32_t tmh0;

    tmh0 = ((uint32_t)msgId << MBOX_TMH0_MID_SHIFT) |
           ((uint32_t)len << MBOX_TMH0_LEN_SHIFT);

    Mbox_Ip_Writel(base, MBOX_TMH0, tmh0);
    Mbox_Ip_Writel(base, MBOX_TMH0_MDP, mdp);
}

/* PRQA S 1505 EOF */
/** *****************************************************************************************************
 * \brief This function fills the short message.
 *
 * \verbatim
 * Syntax             : void Mbox_Ip_FillShortMsg(uint32_t base, uint64_t msg)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - the base physical address
 *                    : msg - the short message
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Fill the short message.
 * \endverbatim
 *******************************************************************************************************/
void Mbox_Ip_FillShortMsg(uint32_t base, uint64_t msg)
{
    Mbox_Ip_Writel(base, MBOX_TMH1, (uint32_t)msg);
    Mbox_Ip_Writel(base, MBOX_TMH2, (uint32_t)(msg >> 32U));
}

/** *****************************************************************************************************
 * \brief This function starts transmission.
 *
 * \verbatim
 * Syntax             : void Mbox_Ip_Send(uint32_t base, uint8_t msgId)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - the base physical address
 *                    : msgId - the message id
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Start transmission.
 * \endverbatim
 *******************************************************************************************************/
void Mbox_Ip_Send(uint32_t base, uint8_t msgId)
{
    uint32_t tmc;
    /* PRQA S 4491 1 */
    tmc = Mbox_Ip_Readl(base, MBOX_TMC(msgId));
    tmc |= (1UL << MBOX_TMC_SEND_SHIFT);

    /* PRQA S 4491 1 */
    Mbox_Ip_Writel(base, MBOX_TMC(msgId), tmc);
}

/** *****************************************************************************************************
 * \brief This function gets the transmission status.
 *
 * \verbatim
 * Syntax             : void Mbox_Ip_TxDone(uint32_t base, uint8_t msgId)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - the base physical address
 *                    : msgId - the message id
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : Transmission status
 *
 * Description        : Get the transmission status.
 * \endverbatim
 *******************************************************************************************************/
bool Mbox_Ip_TxDone(uint32_t base, uint8_t msgId)
{
    uint32_t tmc;

    /* PRQA S 4491,4404,4558 2 */
    tmc = Mbox_Ip_Readl(base, MBOX_TMC(msgId));
    return !(tmc & (1UL << MBOX_TMC_SEND_SHIFT));
}

/** *****************************************************************************************************
 * \brief This function cancel transmission.
 * \verbatim
 * Syntax             : void Mbox_Ip_CancelSend(uint32_t base, uint8_t msgId)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - the base physical address
 *                    : msgId - the message id
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Cancel the message sent.
 * \endverbatim
 *******************************************************************************************************/
void Mbox_Ip_CancelSend(uint32_t base, uint8_t msgId)
{
    uint32_t tmc;

    /* PRQA S 4491 EOF */
    tmc = Mbox_Ip_Readl(base, MBOX_TMC(msgId));
    tmc |= (1UL << MBOX_TMC_CANCEL_SHIFT);
    Mbox_Ip_Writel(base, MBOX_TMC(msgId), tmc);
}

/** *****************************************************************************************************
 * \brief This function gets the cancel status.
 *
 * \verbatim
 * Syntax             : bool Mbox_Ip_CancelDone(uint32_t base, uint8_t msgId)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - the base physical address
 *                    : msgId - the message id
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : Cancel status
 *
 * Description        : Get the cancel status.
 * \endverbatim
 *******************************************************************************************************/
bool Mbox_Ip_CancelDone(uint32_t base, uint8_t msgId)
{
    uint32_t tmc;

    tmc = Mbox_Ip_Readl(base, MBOX_TMC(msgId));
    /* PRQA S 4404,4558 1 */
    return !!(tmc & (1UL << MBOX_TMC_CANCEL_STATUS_SHIFT));
}

/** *****************************************************************************************************
 * \brief This function Fills the wakeup message.
 *
 * \verbatim
 * Syntax             : void Mbox_Ip_FillWakeUpMsg(uint32_t base, uint32_t msg)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - the base physical address
 *                    : msg - wakeup message
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Fill the wakeup message.
 * \endverbatim
 *******************************************************************************************************/
void Mbox_Ip_FillWakeUpMsg(uint32_t base, uint32_t msg)
{
    Mbox_Ip_Writel(base, MBOX_WAKEUP_MSG, msg);
}

/** *****************************************************************************************************
 * \brief This function gets the wakeup source.
 *
 * \verbatim
 * Syntax             : uint32_t Mbox_Ip_GetWakeUpSrc(uint32_t base)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - the base physical address
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : Wakeup source
 *
 * Description        : Get the wakeup source.
 * \endverbatim
 *******************************************************************************************************/
uint32_t Mbox_Ip_GetWakeUpSrc(uint32_t base)
{
    return Mbox_Ip_Readl(base, MBOX_WAKEUP_SRC) & 0xffffU;
}

/** *****************************************************************************************************
 * \brief This function gets the wakeup message.
 *
 * \verbatim
 * Syntax             : uint32_t Mbox_Ip_GetWakeUpMsg(uint32_t base)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - the base physical address
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : Wakeup message
 *
 * Description        : Get the wakeup message.
 * \endverbatim
 *******************************************************************************************************/
uint32_t Mbox_Ip_GetWakeUpMsg(uint32_t base)
{
    return Mbox_Ip_Readl(base, MBOX_WAKEUP_MSG);
}

/** *****************************************************************************************************
 * \brief This function sends wakeup request.
 *
 * \verbatim
 * Syntax             : void Mbox_Ip_SendWakeUp(uint32_t base, uint8_t msgId, uint16_t mdp)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - the base physical address
 *                    : msgId - the message id
 *                    : mdp - the target core mask
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Send wakeup request.
 * \endverbatim
 *******************************************************************************************************/
void Mbox_Ip_SendWakeUp(uint32_t base, uint8_t msgId, uint16_t mdp)
{
    uint32_t tmc;

    tmc = Mbox_Ip_Readl(base, MBOX_TMC_WAKEUP(msgId));
    tmc |= mdp;
    Mbox_Ip_Writel(base, MBOX_TMC_WAKEUP(msgId), tmc);
}

/** *****************************************************************************************************
 * \brief This function gets wakeup status.
 *
 * \verbatim
 * Syntax             : bool Mbox_Ip_WakeUpDone(uint32_t base, uint16_t mdp)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - the base physical address
 *                    : mdp - the target core mask
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : Wakeup status
 *
 * Description        : Get wakeup status.
 * \endverbatim
 *******************************************************************************************************/
bool Mbox_Ip_WakeUpDone(uint32_t base, uint16_t mdp)
{
    uint32_t status;

    status = Mbox_Ip_Readl(base, MBOX_TPWES);
    /* PRQA S 4404,4558 1 */
    return !(status & mdp);
}

/** *****************************************************************************************************
 * \brief This function acknowledges mailbox wakeup.
 *
 * \verbatim
 * Syntax             : void Mbox_Ip_AckWakeUp(uint32_t base)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - the base physical address
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Acknowledge mailbox wakeup.
 * \endverbatim
 *******************************************************************************************************/
void Mbox_Ip_AckWakeUp(uint32_t base)
{
    Mbox_Ip_Writel(base, MBOX_RWC, 0x01U);
}

/** *****************************************************************************************************
 * \brief This function gets the received message source.
 *
 * \verbatim
 * Syntax             : uint64_t Mbox_Ip_Get_Status(uint32_t base)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - the base physical address
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : The received message source
 *
 * Description        : Get the received message source.
 * \endverbatim
 *******************************************************************************************************/
uint64_t Mbox_Ip_GetStatus(uint32_t base)
{
    uint64_t status;

    status = Mbox_Ip_Readl(base, MBOX_TMS + 0x04U);
    status <<= 32U;
    status |= Mbox_Ip_Readl(base, MBOX_TMS);

    return status;
}

/** *****************************************************************************************************
 * \brief This function acknowledges mailbox message.
 *
 * \verbatim
 * Syntax             : void Mbox_Ip_Ack(uint32_t base, uint16_t procId, uint8_t msgId)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - the base physical address
 *                    : procId - the target core id
 *                    : msgId - the message id
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Acknowledge mailbox message
 * \endverbatim
 *******************************************************************************************************/
void Mbox_Ip_Ack(uint32_t base, uint16_t procId, uint8_t msgId)
{
    uint64_t rmc = (1ULL << ((procId << 2U) + msgId));

    Mbox_Ip_Writel(base, MBOX_RMC, (uint32_t)rmc);
    Mbox_Ip_Writel(base, MBOX_RMC + 0x04U, (uint32_t)(rmc >> 32U));
}

/** *****************************************************************************************************
 * \brief This function enables/disable ack interrupt.
 *
 * \verbatim
 * Syntax             : void Mbox_Ip_EnableAckInterrupt(uint32_t base, bool en)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - the base physical address
 *                    : en - 1:enable,0:disable
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Enable/disable ack interrupt.
 * \endverbatim
 *******************************************************************************************************/
void Mbox_Ip_EnableAckInterrupt(uint32_t base, bool en)
{
    /* PRQA S 3344 1 */
    if (en)
    {
        Mbox_Ip_Writel(base, MBOX_TACK_INT_EN, 0x01U);
    }
    else
    {
        Mbox_Ip_Writel(base, MBOX_TACK_INT_EN, 0x00U);
    }
}

/** *****************************************************************************************************
 * \brief This function gets short message.
 *
 * \verbatim
 * Syntax             : uint64_t Mbox_Ip_GetShortMsg(uint32_t base, uint16_t procId, uint8_t msgId)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - the base physical address
 *                    : procId - the target core id
 *                    : msgId - the message id
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : Short message
 *
 * Description        : Get short message.
 * \endverbatim
 *******************************************************************************************************/
uint64_t Mbox_Ip_GetShortMsg(uint32_t base, uint16_t procId, uint8_t msgId)
{
    uint64_t rmh_data;

    /* PRQA S 1891,4491 1 */
    rmh_data = Mbox_Ip_Readl(base, MBOX_RMH(2U, procId, msgId));
    rmh_data <<= 32U;
    /* PRQA S 1891,4491 1 */
    rmh_data |= Mbox_Ip_Readl(base, MBOX_RMH(1U, procId, msgId));

    return rmh_data;
}

/** *****************************************************************************************************
 * \brief This function gets message length.
 *
 * \verbatim
 * Syntax             : uint16_t Mbox_Ip_GetMsgLength(uint32_t base, uint16_t procId, uint8_t msgId)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - the base physical address
 *                    : procId - the target core id
 *                    : msgId - the message id
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : Message length
 *
 * Description        : Get message length.
 * \endverbatim
 *******************************************************************************************************/
uint16_t Mbox_Ip_GetMsgLength(uint32_t base, uint16_t procId, uint8_t msgId)
{
    uint32_t rmh0;

    /* PRQA S 1891 1 */
    rmh0 = Mbox_Ip_Readl(base, MBOX_RMH(0U, procId, msgId));
    /* PRQA S 4461 1 */
    return (rmh0 & MBOX_RMH0_LEN_MASK);
}

/** *****************************************************************************************************
 * \brief This function checks if the transmission is over .
 *
 * \verbatim
 * Syntax             : bool Mbox_Ip_CheckTxDone(const Mbox_Ip_ChnCfgType *chnCfg)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : chnCfg - the channel configuration
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : the transmission status
 *
 * Description        : Check the transmission status.
 * \endverbatim
 *******************************************************************************************************/
bool Mbox_Ip_CheckTxDone(const Mbox_Ip_ChnCfgType *chnCfg)
{
    bool ret;

    /* PRQA S 1881 EOF */
    if (MBOX_ACK_INTERRUPT_MODE == chnCfg->ackMode)
    {
        ret = chnCfg->ackStatus;
    }
    else
    {
        ret = Mbox_Ip_TxDone(chnCfg->base, chnCfg->msgId);
    }

    return ret;
}

/** *****************************************************************************************************
 * \brief This function set the transmission is over when ack mode is interrupt.
 *
 * \verbatim
 * Syntax             : bool Mbox_Ip_SetTxDone(Mbox_Ip_ChnCfgType *chnCfg)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : chnCfg - the channel configuration
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : The transmission status
 *
 * Description        : Set the transmission is over.
 * \endverbatim
 *******************************************************************************************************/
bool Mbox_Ip_SetTxDone(Mbox_Ip_ChnCfgType *chnCfg)
{
    /* PRQA S 4404 2 */
    chnCfg->ackStatus = chnCfg->isActive;
    chnCfg->isActive = false;

    return chnCfg->ackStatus;
}

/** *****************************************************************************************************
 * \brief This function waits the message transfer done.
 *
 * \verbatim
 * Syntax             : int32_t Mbox_Ip_WaitTxDone(const Mbox_Ip_ChnCfgType *chnCfg, uint32_t timeOut)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : chnCfg - the channel configuration
 *                    : timeOut - timeout value (ms)
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : The transmission status
 *
 * Description        : Wait the message transfer done.
 * \endverbatim
 *******************************************************************************************************/
int32_t Mbox_Ip_WaitTxDone(const Mbox_Ip_ChnCfgType *chnCfg, uint32_t timeOut)
{
    uint64_t waitTime = 0U;
    /* PRQA S 4423 1 */
    int32_t ret = MBOX_OK;

    /* PRQA S 4116,4558 1 */
    while (!Mbox_Ip_CheckTxDone(chnCfg))
    {
        /* PRQA S 3200 1 */
        LLD_UDELAY(MBOX_IP_POLL_DELAY);
        waitTime += MBOX_IP_POLL_DELAY;
        if (waitTime >= ((uint64_t)timeOut * 1000UL))
        {
            /* PRQA S 4423 1 */
            ret = MBOX_ERR_TIMEOUT;
            break;
        }
    }

    return ret;
}

/** *****************************************************************************************************
 * \brief This function waits the message cancel done.
 *
 * \verbatim
 * Syntax             : int32_t Mbox_Ip_WaitCancelDone(const Mbox_Ip_ChnCfgType *chnCfg, uint32_t timeOut)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : chnCfg - the channel configuration
 *                    : timeOut - timeout value (ms)
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : Cancel status
 *
 * Description        : Wait the message cancel done.
 * \endverbatim
 *******************************************************************************************************/
int32_t Mbox_Ip_WaitCancelDone(const Mbox_Ip_ChnCfgType *chnCfg, uint32_t timeOut)
{
    uint64_t waitTime = 0U;
    /* PRQA S 4423 1 */
    int32_t ret = MBOX_OK;

    Mbox_Ip_CancelSend(chnCfg->base, chnCfg->msgId);

    /* PRQA S 4116,4558 1 */
    while (!Mbox_Ip_CancelDone(chnCfg->base, chnCfg->msgId))
    {
        /* PRQA S 3200 1 */
        LLD_UDELAY(MBOX_IP_POLL_DELAY);
        waitTime += MBOX_IP_POLL_DELAY;
        if (waitTime >= ((uint64_t)timeOut * 1000U))
        {
            /* PRQA S 4423 1 */
            ret = MBOX_ERR_TIMEOUT;
            break;
        }
    }

    return ret;
}

/** *****************************************************************************************************
 * \brief This function waits wakeup done.
 *
 * \verbatim
 * Syntax             : int32_t Mbox_Ip_WaitWakeUpDone(const Mbox_Ip_ChnCfgType *chnCfg, uint32_t timeOut)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : chnCfg - the channel configuration
 *                    : timeOut - timeout value (ms)
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : Wakeup status
 *
 * Description        : Wait wakeup done.
 * \endverbatim
 *******************************************************************************************************/
int32_t Mbox_Ip_WaitWakeUpDone(const Mbox_Ip_ChnCfgType *chnCfg, uint32_t timeOut)
{
    uint64_t waitTime = 0U;
    /* PRQA S 4423 1 */
    int32_t ret = MBOX_OK;

    /* PRQA S 4116,4558 1 */
    while (!Mbox_Ip_WakeUpDone(chnCfg->base, chnCfg->mdp))
    {
        /* PRQA S 3200 1 */
        LLD_UDELAY(MBOX_IP_POLL_DELAY);
        waitTime += MBOX_IP_POLL_DELAY;
        if (waitTime >= ((uint64_t)timeOut * 1000U))
        {
            /* PRQA S 4423 1 */
            ret = MBOX_ERR_TIMEOUT;
            break;
        }
    }

    return ret;
}

/* PRQA S 1505 EOF */
/** *****************************************************************************************************
 * \brief This function sends the message.
 *
 * \verbatim
 * Syntax             : int32_t Mbox_Ip_SendMsg(Mbox_Ip_ChnCfgType *chnCfg, uint64_t msg,
 *                                          uint16_t len, uint32_t timeOut)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : chnCfg - the channel configuration
 *                    : msg - the message
 *                    : len - message length
 *                    : timeOut - timeout value (ms)
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : Cancel status
 *
 * Description        : Wait the message cancel done.
 * \endverbatim
 *******************************************************************************************************/
int32_t Mbox_Ip_SendMsg(Mbox_Ip_ChnCfgType *chnCfg, uint64_t msg, uint16_t len, uint32_t timeOut)
{
    /* PRQA S 4423 1 */
    int32_t ret = MBOX_OK;

    Mbox_Ip_FillMsgHeader(chnCfg->base, chnCfg->msgId, chnCfg->mdp, len);
    Mbox_Ip_FillShortMsg(chnCfg->base, msg);

    /* PRQA S 4404 2 */
    chnCfg->ackStatus = false;
    chnCfg->isActive = true;
    Mbox_Ip_Send(chnCfg->base, chnCfg->msgId);

    if (MBOX_SEND_NOWAIT != timeOut)
    {
        ret = Mbox_Ip_WaitTxDone(chnCfg, timeOut);
        /** #10 send timeout */
        if (MBOX_OK != ret)
        {
            /** #20 cancel the sent message */
            if (MBOX_OK != Mbox_Ip_WaitCancelDone(chnCfg, timeOut))
            {
                /** #30 wait send done again when cancel failed */
                ret = Mbox_Ip_WaitTxDone(chnCfg, timeOut);
            }
            /* PRQA S 4404 1 */
            chnCfg->isActive = false;
        }
    }

    return ret;
}

/** *****************************************************************************************************
 * \brief This function receives the message.
 *
 * \verbatim
 * Syntax             : void Mbox_Ip_RecvMsg(const Mbox_Ip_ChnCfgType *chnCfg)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : chnCfg - the channel configuration
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Receive the message.
 * \endverbatim
 *******************************************************************************************************/
void Mbox_Ip_RecvMsg(const Mbox_Ip_ChnCfgType *chnCfg)
{
    uint16_t procId;
    uint8_t msgId;
    uint32_t msgMask;
    uint64_t msgVal;
    uint16_t msgLen;
    uint64_t state = Mbox_Ip_GetStatus(chnCfg->base);

    if (0ULL != state)
    {
        for (procId = 0U; procId < MBOX_PROC_ID_NUM; procId++)
        {
            /* PRQA S 4461 1 */
            msgMask = (state >> (procId << 2U)) & 0xfU;
            for (msgId = 0U; msgId < MBOX_MSG_NUM; msgId++)
            {
                /* PRQA S 1891,4558 1 */
                if (!(msgMask & (1U << msgId)))
                {
                    continue;
                }
                /* PRQA S 3344 1 */
                if (chnCfg->cbFunc)
                {
                    msgVal = Mbox_Ip_GetShortMsg(chnCfg->base, procId, msgId);
                    msgLen = Mbox_Ip_GetMsgLength(chnCfg->base, procId, msgId);
                    chnCfg->cbFunc(procId, msgVal, msgLen, chnCfg->recvArg);
                }
                Mbox_Ip_Ack(chnCfg->base, procId, msgId);
            }
        }
    }
}

/** *****************************************************************************************************
 * \brief This function wakeups the target core.
 *
 * \verbatim
 * Syntax             : int32_t Mbox_Ip_WakeUp(const Mbox_Ip_ChnCfgType *chnCfg, uint32_t msg, uint32_t timeOut)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : chnCfg - the channel configuration
 *                    : msg - the wakeup message
 *                    : timeOut - timeout value (ms)
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : wakeup status
 *
 * Description        : Wakeup the target core.
 * \endverbatim
 *******************************************************************************************************/
int32_t Mbox_Ip_WakeUp(const Mbox_Ip_ChnCfgType *chnCfg, uint32_t msg, uint32_t timeOut)
{
    int32_t ret;

    Mbox_Ip_FillWakeUpMsg(chnCfg->base, msg);
    Mbox_Ip_SendWakeUp(chnCfg->base, 0U, chnCfg->mdp);

    ret = Mbox_Ip_WaitWakeUpDone(chnCfg, timeOut);

    return ret;
}

/** *****************************************************************************************************
 * \brief This function handles the wakeup request.
 *
 * \verbatim
 * Syntax             : void Mbox_Ip_HandleWakeUp(const Mbox_Ip_ChnCfgType *chnCfg)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : chnCfg - the channel configuration
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Handle the wakeup.
 * \endverbatim
 *******************************************************************************************************/
void Mbox_Ip_HandleWakeUp(const Mbox_Ip_ChnCfgType *chnCfg)
{
    uint32_t wakeupMsg = Mbox_Ip_GetWakeUpMsg(chnCfg->base);
    uint32_t wakeupSrc = Mbox_Ip_GetWakeUpSrc(chnCfg->base);

    /* PRQA S 3344 1 */
    if (chnCfg->wakeupCbFunc)
    {
        /* PRQA S 4461 1 */
        chnCfg->wakeupCbFunc(wakeupSrc, wakeupMsg, chnCfg->wakeupArg);
    }

    Mbox_Ip_AckWakeUp(chnCfg->base);
}

#if (defined(CFG_PLATFORM_MCAL))
#define MAILBOX_STOP_SEC_CODE
#include "Mailbox_MemMap.h"
#endif

/* End of file */
